package br.ufu.comp.pdi.utils;

public class Matrix {

	public static double[][] multPontoPonto(int[][] originalImg, double[][] mask) throws Exception {

		if (originalImg[0].length != mask[0].length || originalImg.length != mask.length) {
			throw new Exception("Tamanhos diferentes");
		}

		double[][] im3 = new double[originalImg[0].length][originalImg.length];

		for (int x = 0; x < originalImg[0].length; x++) {
			for (int y = 0; y < originalImg.length; y++) {
				im3[x][y] = originalImg[x][y] * mask[x][y];
			}
		}

		return im3;
	}
	
	public static double[][] multPontoPonto(double[][] originalImg, double valor) throws Exception {

		double[][] im3 = new double[originalImg[0].length][originalImg.length];

		for (int x = 0; x < originalImg[0].length; x++) {
			for (int y = 0; y < originalImg.length; y++) {
				im3[x][y] = originalImg[x][y] * valor;
			}
		}

		return im3;
	}
	
	public static int[][] addPontoPonto(int[][] img1, int[][] img2) throws Exception {

		if (img1[0].length != img2[0].length || img1.length != img2.length) {
			throw new Exception("Tamanhos diferentes");
		}

		int[][] im3 = new int[img1[0].length][img1.length];

		for (int x = 0; x < img1[0].length; x++) {
			for (int y = 0; y < img1.length; y++) {
				im3[x][y] = truncate(img1[x][y] + img2[x][y]);
			}
		}

		return im3;
	}
	
	public static int[][] mult(int[][] matrix, double scalar) {
		
		int[][] newMatrix = new int[matrix[0].length][matrix.length];
		
		for(int i = 0; i < newMatrix[0].length; i++) {
			for(int j = 0; j < newMatrix.length; j++) {
				newMatrix[i][j] = (int) scalar * matrix[i][j];
			}
		}
		
		return newMatrix;
	}
	
	public static double[][] divPontoPonto(int[][] originalImg, double[][] mask) throws Exception {

		if (originalImg[0].length != mask[0].length || originalImg.length != mask.length) {
			throw new Exception("Tamanhos diferentes");
		}

		double[][] im3 = new double[originalImg[0].length][originalImg.length];

		for (int x = 0; x < originalImg[0].length; x++) {
			for (int y = 0; y < originalImg.length; y++) {
				im3[x][y] = originalImg[x][y] / mask[x][y];
			}
		}

		return im3;
	}
	
	public static double[][] divPontoPonto(int[][] originalImg, double valor) throws Exception {

		double[][] im3 = new double[originalImg[0].length][originalImg.length];

		for (int x = 0; x < originalImg[0].length; x++) {
			for (int y = 0; y < originalImg.length; y++) {
				im3[x][y] = originalImg[x][y] / valor;
			}
		}

		return im3;
	}
	
	public static double[][] normalizar(double[][] mask) throws Exception {

		double[][] im3 = new double[mask[0].length][mask.length];
		double soma = somaMatrizDouble(mask);
		
		for (int x = 0; x < mask[0].length; x++) {
			for (int y = 0; y < mask.length; y++) {
				im3[x][y] = mask[x][y] / soma;
			}
		}

		return im3;
	}
	
	public static int[][] removeLineAndColumn(int[][] originalImage) {
		int[][] newImage = new int[originalImage[0].length - 1][originalImage.length - 1];
		
		for (int i = 0, m = 1; i < newImage[0].length; i++, m++) {
			for (int j = 0, n = 1; j < newImage.length; j++, n++) {
				newImage[i][j] = originalImage[m][n];
			}
		}
		
		return newImage;
	}

	public static int[][] geraSubMatriz(int[][] im1, int x1, int dx, int y1, int dy) {
		
		int x2 = x1 + dx;
		int y2 = y1 + dy;
		
		int[][] im2 = new int[dx][dy];
		for (int x = x1, index = 0; x < x2; x++, index++) {
			for (int y = y1, indey = 0; y < y2; y++, indey++) {
				im2[index][indey] = im1[x][y];
			}
		}
		return im2;
	}

	public static int somaMatriz(double[][] im) {
		double soma = 0;
		for (int x = 0; x < im[0].length; x++) {
			for (int y = 0; y < im.length; y++) {
				soma += im[x][y];
			}
		}
		
		return truncate(soma);
	}
	
	public static double somaMatrizDouble(double[][] im) {
		double soma = 0;
		for (int x = 0; x < im[0].length; x++) {
			for (int y = 0; y < im.length; y++) {
				soma += im[x][y];
			}
		}
		
		return soma;
	}
	
	public static int[][] sub(int[][] a, int[][] b) throws Exception {
		
		if(a.length != b.length || a[0].length != b[0].length){
			throw new Exception("Tamanhos diferentes");
		}
		
		int[][] c = new int[a.length][a[0].length];
		
		for(int i = 0; i < a[0].length; i++) {
			for(int j = 0; j < a.length; j++) {
				c[i][j] = truncate(a[i][j] - b[i][j]);
			}
		}
		
		
		return c;
	}
	
	public static double[][] toDoubleMatrix(int[][] original) {
		double[][] newMatrix = new double[original.length][original[0].length];
		
		for(int i = 0; i < original[0].length; i++){
			for(int j = 0; j < original.length; j++){
				newMatrix[i][j] = (double) original[i][j];
			}
		}
		
		return newMatrix;
	}
	
	public static int truncate(double value) {
		if(value < 0) {
			return 0;
		} else if (value > 255) {
			return 255;
		}
		return (int) value;
	}
	
	public static int[][] doubleToInt(double[][] mask)
	{
		int nx = mask[0].length;
		int ny = mask.length;
		
		int[][] discrete = new int[nx][ny];
		
		for (int x = 0; x <= nx; x++) {
			for (int y = 0; y <= ny; y++){
				discrete[x][y] = (int) mask[x][y];		
			}	
		}
		
		return discrete;
	}
	
}
